对于基本类型，如int、double或指针类型，没有默认构造函数可以初始化。相反，任何未初始化的局部变量都有一个未定义的值:

\begin{lstlisting}[style=styleCXX]
void foo()
{
	int x; // x has undefined value
	int* ptr; // ptr points to anywhere (instead of nowhere)
}
\end{lstlisting}

若编写模板，并想让模板类型的变量用默认值初始化，就会遇到一个问题，简单的定义对内置类型并没有进行初始化:

\begin{lstlisting}[style=styleCXX]
template<typename T>
void foo()
{
	T x; // x has undefined value if T is built-in type
}
\end{lstlisting}

因此，可以显式调用内置类型的默认构造函数，该构造函数用0初始化内置类型(bool为false，指针为nullptr)。因此，即使是内置类型，也可以通过编写以下代码来确保正确的初始化:

\begin{lstlisting}[style=styleCXX]
template<typename T>
void foo()
{
	T x{}; // x is zero (or false) if T is a built-in type
}
\end{lstlisting}

这种初始化方式称为值初始化，要么调用提供的构造函数，要么对对象进行零初始化。即使构造函数是显式的，也可以这样做。

C++11前，正确初始化的语法是

\begin{lstlisting}[style=styleCXX]
T x = T(); // x is zero (or false) if T is a built-in type
\end{lstlisting}

C++17前，这种机制(现在仍受支持)只有在为复制初始化选择的构造函数不是显式的情况下才有效。在C++17中，省略了强制复制，从而避免了这种限制，而且两种语法都有效。但若没有默认构造函数，带大括号的初始化表示法可以使用初始化列表构造函数。

\begin{tcolorbox}[colback=webgreen!5!white,colframe=webgreen!75!black]
\hspace*{0.75cm}对于某种类型X，有参数类型为std::initializer\_list<X>的构造函数。
\end{tcolorbox}

为了确保将类型参数化的类模板成员初始化，可以定义默认构造函数，使用带大括号的初始化式来初始化成员:

\begin{lstlisting}[style=styleCXX]
template<typename T>
class MyClass {
private:
	T x;
public:
	MyClass() : x{} { // ensures that x is initialized even for built-in types
	}
	...
};
\end{lstlisting}

C++11前的语法

\begin{lstlisting}[style=styleCXX]
MyClass() : x() { // ensures that x is initialized even for built-in types
}
\end{lstlisting}

在后续标准中使用，仍然有效。

C++11后，还可以为非静态成员提供默认初始化，这样也可以实现以下操作:

\begin{lstlisting}[style=styleCXX]
template<typename T>
class MyClass {
private:
	T x{}; // zero-initialize x unless otherwise specified
	...
};
\end{lstlisting}

但是，请注意默认参数不能使用该语法。例如,

\begin{lstlisting}[style=styleCXX]
template<typename T>
void foo(T p{}) { // ERROR
	...
}
\end{lstlisting}

必须这样写:

\begin{lstlisting}[style=styleCXX]
template<typename T>
void foo(T p = T{}) { // OK (must use T() before C++11)
	...
}
\end{lstlisting}





















